﻿using Common.AspNetCore;
using Common.RunModels.File;
using File.Api.Models;
using File.Api.Repository;
using File.Api.Utils;
using File.Data.Entity;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace File.Api.Service
{
    public class UploadFileService : CommonService
    {
        private readonly IConfiguration configuration;
        private readonly FileRepository fileRepository;

        public UploadFileService(IServiceProvider provider, IConfiguration config, FileRepository file) : base(provider)
        {
            this.configuration = config;
            this.fileRepository = file;
        }

        public async Task<List<UploadFile>> UploadFilesAsync(List<FileModel> list)
        {
            List<UploadFile> r = null;
            try
            {
                list.ForEach(t =>
                {
                    if (t.FileData != null)
                    {
                        t.FileLength = t.FileData.Length;
                    }
                });
                r = await SaveFileAsync(list);
            }
            catch (Exception ex)
            {
                this.ThrowError("06900000", ex.Message);
            }

            return r;
        }

        public async Task<UploadFileGroup> UploadFileGroupAsync(FileGroupModel fileGroupModel)
        {
            if (fileGroupModel == null)
            {
                return null;
            }

            UploadFileGroup ret = new UploadFileGroup();
            try
            {
                SaveFileGroupModel model = new SaveFileGroupModel();
                foreach (var gdetail in fileGroupModel.Details)
                {
                    if (gdetail.FileData != null)
                    {
                        gdetail.FileLength = gdetail.FileData.Length;
                    }

                    if (gdetail.FileData != null && gdetail.FileData.Any())
                    {
                        List<FileGroupDetailModel> gs = new List<FileGroupDetailModel>();
                        gs.Add(gdetail);
                        await SaveFileAsync(gs);
                    }

                    var details = gdetail.Details.ToList();
                    details.ForEach(t =>
                    {
                        if (t.FileData != null)
                        {
                            t.FileLength = t.FileData.Length;
                        }
                    });
                    await SaveFileAsync(details);
                    t_file_group fileGroup = new t_file_group()
                    {
                        file_id = gdetail.FileId,
                        file_length = gdetail.FileLength,
                        file_name = gdetail.FileName,
                        user_name = gdetail.UserName,
                        file_type = gdetail.FileType
                    };
                    this.SetEntityId(fileGroup);
                    model.AddFileGroups.Add(fileGroup);
                    var uploadFileGroup = new UploadFileGroupDetail()
                    {
                        FileId = fileGroup.file_id,
                        FileName = fileGroup.file_name,
                        GroupId = fileGroup.id
                    };
                    ret.Details.Add(uploadFileGroup);
                    foreach (var s in details)
                    {
                        t_file_group_detail d = new t_file_group_detail()
                        {
                            file_group_id = fileGroup.id,
                            file_id = s.FileId,
                            index = s.Index
                        };
                        this.SetEntityId(d, fileGroup.id);
                        model.AddFileGroupDetails.Add(d);
                        var ugd = new UploadFileGroupFileDetail() { FileId = d.file_id, FileName = s.FileName };
                        uploadFileGroup.Details.Add(ugd);
                    }
                }

                await this.SaveFileGroupModelAsync(model);
            }
            catch (Exception ex)
            {
                this.ThrowError("06900000", ex.Message);
            }

            return ret;
        }

        private async Task SaveFileModelAsync(SaveFileModel model)
        {
            await this.fileRepository.SaveFileModelAsync(model);
        }

        private async Task SaveFileGroupModelAsync(SaveFileGroupModel model)
        {
            await this.fileRepository.SaveFileGroupModelAsync(model);
        }

        private async Task<List<UploadFile>> SaveFileAsync<T>(List<T> list) where T : FileModel
        {
            var ftpParam = FileUtils.GetFtpFileParam(this.configuration);
            if (ftpParam != null)
            {
                foreach (var f in list)
                {
                    await FtpFileUtils.UploadFileAsync(f, ftpParam);
                }
            }
            else
            {
                var localParam = FileUtils.GetLocalFileParam(this.configuration);
                if (localParam == null)
                {
                    localParam = new LocalFileParam() { RootPath = AppContext.BaseDirectory };
                }

                foreach (var f in list)
                {
                    await LocalFileUtils.UploadFileAsync(f, localParam);
                }
            }

            List<UploadFile> uploadFiles = new List<UploadFile>();
            SaveFileModel model = new SaveFileModel();
            foreach (var f in list)
            {
                t_file r = new t_file();
                this.SetEntityId(r);
                r.file_name = f.FileName;
                r.file_type = f.FileType;
                r.user_name = f.UserName;
                r.file_path = f.FilePath;
                r.file_length = f.FileLength;
                f.FileId = r.id;
                var up = new UploadFile() { FileId = r.id, FileName = r.file_name };
                model.AddFiles.Add(r);
                uploadFiles.Add(up);
            }

            await this.SaveFileModelAsync(model);
            return uploadFiles;
        }
    }
}
